package com.zbs.framework.dao.rolefunction.service.impl;

import com.zbs.framework.common.utils.ErrorAssert;
import com.zbs.framework.dao.function.entity.Function;
import com.zbs.framework.dao.permission.entity.Permission;
import com.zbs.framework.dao.rolefunction.repository.RoleFunctionRepository;
import com.zbs.framework.dao.rolefunction.repository.UserFunctionRepository;
import com.zbs.framework.dao.rolefunction.service.UserFunctionService;
import com.zbs.framework.dao.rolefunction.service.model.UserFunctionInfo;
import com.zbs.framework.dao.user.repository.UserRoleRepository;
import com.zbs.framework.dao.userfunction.entity.UserFunction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * Created by Zbs
 * 2019-04-28 11:38
 */
@Service
@Transactional
public class UserFunctionServiceImpl implements UserFunctionService {

    @Autowired
    private UserFunctionRepository userFunctionRepository;

    @Autowired
    private RoleFunctionRepository roleFunctionRepository;

    @Autowired
    private UserRoleRepository userRoleRepository;

    @Override
    
    public void editUserFunctions(Long userId, List<Long> functionIds) {
        // 参数检查
        ErrorAssert.notNull(userId, "User id can not be null");
        // 查找原有功能
        List<Long> prevFuncIds = userFunctionRepository.findFunctionIds(userId);
        // 获取需要添加的功能
        List<Long> funcsToAdd = notContained(prevFuncIds, functionIds);
        // 获取需要删除的功能
        List<Long> funcsToReduce = notContained(functionIds, prevFuncIds);
        // 执行添加
        addAllFuncs(userId, funcsToAdd);
        // 执行删除
        reduceAllFuncs(userId, funcsToReduce);
    }

    /**
     * 添加功能
     * @param userId
     *          用户Id
     * @param funcsToAdd
     *          待添加功能
     */
    private void addAllFuncs(Long userId, List<Long> funcsToAdd) {
        if (userId == null || CollectionUtils.isEmpty(funcsToAdd)) return;
        List<UserFunction> list = new ArrayList<>();
        funcsToAdd.forEach(funcId -> {
            list.add(new UserFunction(userId, funcId));
        });
        userFunctionRepository.saveAll(list);
    }

    private void reduceAllFuncs(Long userId, List<Long> funcsToReduce) {
        if (userId == null || CollectionUtils.isEmpty(funcsToReduce)) return;
        funcsToReduce.forEach(funcId -> {
            userFunctionRepository.deleteByUserIdAndFunctionId(userId, funcId);
        });
    }

    private List<Long> notContained(List<Long> source, List<Long> candidates) {
        if (CollectionUtils.isEmpty(source)) return candidates;
        if (CollectionUtils.isEmpty(candidates)) return null;
        List<Long> result = new ArrayList<>();
        candidates.forEach(id -> {
            if (!source.contains(id)) result.add(id);
        });
        return result;
    }

    @Override
    public List<Long> getFuncIds(Long userId) {
        // 参数检查
        ErrorAssert.notNull(userId, "User id can not be null");
        //
        return userFunctionRepository.findFunctionIds(userId);
    }

    @Override
    public List<UserFunctionInfo> getUserAllFunctions(Long userId) {
        // 参数检查
        ErrorAssert.notNull(userId, "User id can not be null");
        // 获取直接分配给用户的功能
        Set<Long> fIdSet = new HashSet<>();
        List<UserFunctionInfo> result = new ArrayList<>();
        List<Function> dFuncs = userFunctionRepository.findFunctions(userId);
        if (!CollectionUtils.isEmpty(dFuncs)) {
            dFuncs.forEach(func -> {
                if (fIdSet.add(func.getId())) {
                    result.add(new UserFunctionInfo(func.getId(), func.getIdentifier(), func.getName()));
                }
            });
        }
        // 获取用户角色
        Integer[] roleIds = userRoleRepository.findRoleIds(userId);
        // 获取角色功能
        if ((roleIds == null) || roleIds.length == 0) return result;
        List<Function> rFuncs = roleFunctionRepository.findFunctions(roleIds);
        if (CollectionUtils.isEmpty(rFuncs)) return result;
        rFuncs.forEach(func -> {
            if (fIdSet.add(func.getId())) {
                result.add(new UserFunctionInfo(func.getId(), func.getIdentifier(), func.getName()));
            }
        });
        return result;
    }

    @Override
    public boolean existsUserAllFunctions(Long userId,String identifier) {
        // 参数检查
        ErrorAssert.notNull(userId, "User id can not be null");
        // 获取直接分配给用户的功能
        Integer exists = this.userFunctionRepository.existsFunctionsByIdentifier(userId, identifier);
        if (exists > 0) {
            return true;
        }
        // 获取用户角色
        Integer[] roleIds = userRoleRepository.findRoleIds(userId);
        // 获取角色功能
        if ((roleIds == null) || roleIds.length == 0) return false;
        return this.roleFunctionRepository.findFunctions(roleIds, identifier) > 0;
    }

    @Override
    public Set<String> getAllUserPermissions(Long userId, Integer[] roleIds) {
        Set<String> permSet = new HashSet<>();
        // 获取用户权限
        List<Permission> perms = userFunctionRepository.findPermissions(userId);
        if (!CollectionUtils.isEmpty(perms)) {
            perms.forEach(p -> permSet.add(p.getServiceName() + "::" + p.getName()));
        }
        // 获取用户拥有角色权限

        if(roleIds != null && roleIds.length != 0) {
            List<Integer> roleIdList = new ArrayList<>(roleIds.length);
            Collections.addAll(roleIdList, roleIds);
            List<Permission> rolePerms = roleFunctionRepository.findPermissions(roleIdList);
            if (!CollectionUtils.isEmpty(rolePerms)) {
                rolePerms.forEach(p -> permSet.add(p.getServiceName() + "::" + p.getName()));
            }
        }
        return permSet;
    }


}
